package com.example.services;

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.context.WebApplicationContext;

import com.example.ShoppingCartApiApplication;
import com.example.exceptions.CartNotFoundException;
import com.example.exceptions.CustomerNotFoundException;
import com.example.exceptions.ProductNotFoundException;
import com.example.models.Cart;
import com.example.models.Customer;
import com.example.models.ItemToPurchase;
import com.example.models.Product;
import com.example.repositories.CartRepository;
import com.example.repositories.CustomerRepository;
import com.example.repositories.ProductRepository;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ShoppingCartApiApplication.class)
@WebAppConfiguration
@IntegrationTest({"server.port=9090"})
public class CartServiceIT {

	@Autowired
    private CartRepository cartRepository;
	
	@Autowired
    private CartService cartService;
	
	@Autowired
	private ProductRepository productRepository;
	
	@Autowired
	private CustomerRepository customerRepository;
	
	@Autowired
    private WebApplicationContext webApplicationContext;
	
	Cart cart1,cart2;
	private ArrayList<Cart> carts = new ArrayList<Cart>();
	Customer customer,customer2;
	Set<ItemToPurchase> set1,set2;
	Product p1;
	
	@Before
    public void setup() {
		customer = customerRepository.save(new Customer("customerId","c1","c1Name","c1LastName"));
		customer2 = customerRepository.save(new Customer("customer2Id","c2","c2Name","c2LastName"));
	        
	     p1 = productRepository.save(new Product("p1Id",100));
//	     Product p2 = new Product("p2Id",100);
	     ItemToPurchase item1 = new ItemToPurchase("it1Id",p1.getId(),10,cart1);
//	     ItemToPurchase item2 = new ItemToPurchase("it2Id",p2.getId(),15,cart2);
	     ItemToPurchase item3 = new ItemToPurchase("it3Id",p1.getId(),25,cart1);   
	     set1 = new HashSet<ItemToPurchase>();
	     set2 = new HashSet<ItemToPurchase>();
	     set1.add(item1);
//	     set1.add(item2);
	     set2.add(item3);
	     
	     this.cart1 = cartRepository.save(new Cart("c1Id",set1, customer));
	     this.cart2 = cartRepository.save(new Cart("c2Id",set2, customer2));
	     carts.add(cart1);
	     carts.add(cart2);
	}
	
	@Test
	public void saveCart() {
		cartService.saveCart(cart1);
	}
	
	@Test(expected = CustomerNotFoundException.class) 
	public void saveCartWithUnknownCustomer() {
		Customer notSaved = new Customer("123");
		cart1.setCustomer(notSaved);
		cartService.saveCart(cart1);
	}
	
	@Test(expected = ProductNotFoundException.class) 
	public void saveCartWithUnknownProduct() {
		Product notSaved = new Product("123");
		cart1.getItems().iterator().next().setProduct_id(notSaved.getId());
		cartService.saveCart(cart1);
	}
	
	@Test
	public void findCart() {
		Cart searchedCart = cartService.find(cart1.getId());
		assertEquals(searchedCart.getCustomer(), cart1.getCustomer());
//		assertEquals(searchedCart.getItems(), cart1.getItems());
	}
	
	@Test(expected = CartNotFoundException.class) 
	public void cartNotFound() {
		cartService.find("123");
	}
	
	@Test
	public void deleteCart() {
		cartService.deleteCart(cart1.getId());
	}
	
	@Test(expected = CartNotFoundException.class) 
	public void deleteCartNotFound() {
		cartService.deleteCart("123");
	}
	
	@Test
	public void getAllCarts(){
		Collection<Cart> result = cartService.findAll();
		Iterator<Cart> iterator = result.iterator();
		int index=0;
		while(iterator.hasNext()){
			Cart next = iterator.next();
			assertEquals(carts.get(index).getCustomer(), next.getCustomer());
//			assertEquals(carts.get(index).getItems(), next.getItems());
			index++;
		}
	}
	
	@Test
	public void buyNotSavedCart() throws Exception {
		cartService.buy(cart1);
	}
	
	@Test
	public void buySavedCart() throws Exception {
		cartService.buy(cart1.getId());
	}
}
